#include "TestFactory.h"
#include "Tests.h"

namespace TestFactory
{

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

void RunAllTests ()
{
	TestLifeTime::Run ();
	TestNull::Run ();
	TestCopy::Run ();
	TestAccess::Run ();
	TestCounter::Run ();
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

Factory < DummyInterface > Dummy::factory;
int Dummy::dummiesCreated = 0;
int Dummy::dummiesDeleted = 0;

DummyPtr Dummy::Spawn ()
{
	return factory.CreateNewObject < Dummy > ();
}

void Dummy::CheckInnocence ()
{
	assert ( factory.ObjectsCount () == 0 );
}

int Dummy::Count ()
{
	return factory.ObjectsCount ();
}

Dummy::Dummy ()
: somethingDid ( 0 )
{
	dummiesCreated++;
}

Dummy::~Dummy ()
{
	dummiesDeleted++;
}

void Dummy::DoSomething ()
{
	somethingDid++;
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

std::string TestBase::SuiteIdentity ()
{
	return "TestFactory";
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

TestLifeTime::TestLifeTime ()
{
	Dummy::dummiesCreated = 0;
	Dummy::dummiesDeleted = 0;
	DummyInterfacePtr dummy ( Dummy::Spawn () );
	TEST_ASSUMPTION ( Dummy::dummiesCreated == 1 );
	dummy.Delete ();
	TEST_ASSUMPTION ( Dummy::dummiesDeleted == 1 );
}

std::string TestLifeTime::TestIdentity ()
{
	return "TestLifeTime";
}

void TestLifeTime::Run ()
{
	TestLifeTime ();
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

TestNull::TestNull ()
{
	DummyInterfacePtr dummy;
	TEST_ASSUMPTION ( dummy.IsNull () );
	dummy = Dummy::Spawn ();
	TEST_ASSUMPTION ( ! dummy.IsNull () );
	dummy.Delete ();
	TEST_ASSUMPTION ( dummy.IsNull () );
}

std::string TestNull::TestIdentity ()
{
	return "TestNull";
}

void TestNull::Run ()
{
	TestNull ();
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

TestCopy::TestCopy ()
{
	DummyInterfacePtr dummy ( Dummy::Spawn () );
	
	DummyInterfacePtr copyByConstructor ( dummy );
	DummyInterfacePtr copyByOperatorEqual;
	copyByOperatorEqual = dummy;
	
	TEST_ASSUMPTION ( ! copyByConstructor.IsNull () );
	TEST_ASSUMPTION ( ! copyByOperatorEqual.IsNull () );

	dummy.Delete ();

	TEST_ASSUMPTION ( copyByConstructor.IsNull () );
	TEST_ASSUMPTION ( copyByOperatorEqual.IsNull () );
}

std::string TestCopy::TestIdentity ()
{
	return "TestCopy";
}

void TestCopy::Run ()
{
	TestCopy ();
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

TestAccess::TestAccess ()
{
	DummyPtr dummy ( Dummy::Spawn () );
	DummyInterfacePtr dummyPtr ( dummy );
	dummyPtr->DoSomething ();
	TEST_ASSUMPTION ( dummy->somethingDid == 1 );
	dummyPtr.Delete ();
}

std::string TestAccess::TestIdentity ()
{
	return "TestAccess";
}

void TestAccess::Run ()
{
	TestAccess ();
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

TestCounter::TestCounter ()
{
	TEST_ASSUMPTION ( Dummy::Count () == 0 );

	DummyInterfacePtr dummy1 ( Dummy::Spawn () );
	TEST_ASSUMPTION ( Dummy::Count () == 1 );
	
	DummyInterfacePtr dummy2 ( Dummy::Spawn () );
	TEST_ASSUMPTION ( Dummy::Count () == 2 );
	
	DummyInterfacePtr dummyCopyByConstructor ( dummy1 );
	TEST_ASSUMPTION ( Dummy::Count () == 2 );
	
	DummyInterfacePtr dummyCopyByOperatorEqual;
	dummyCopyByOperatorEqual = dummy2;
	TEST_ASSUMPTION ( Dummy::Count () == 2 );
	
	dummy1.Delete ();
	TEST_ASSUMPTION ( Dummy::Count () == 1 );
	
	dummy2.Delete ();
	TEST_ASSUMPTION ( Dummy::Count () == 0 );
}

std::string TestCounter::TestIdentity ()
{
	return "TestCounter";
}

void TestCounter::Run ()
{
	TestCounter ();
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

}; // namespace TestFactory
